package com.yj.springbootmiaosha.controller;

import com.yj.springbootmiaosha.entity.DistributeLock;
import com.yj.springbootmiaosha.mapper.DistributeLockDao;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@RestController
@Slf4j
public class DistributeLockController {


    static Lock lock = new ReentrantLock();

    /**
     * 使用jvm 级别的锁无法控制分布式系统的并发问题
     */
    @GetMapping("singleLock")
    public void singleLock(){
        log.info("进入 singleLock 方法");
        try {
            lock.lock();
            log.info("获取到 singleLock 锁");
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    @Resource
    private DistributeLockDao distributeLockDao;

    /**
     * 使用mysql 数据控制分布式锁的问题
     *  select ... for update 行锁
     *
     *  缺点：
     *      当并发量大的时候，对数据库的压力大
     *          如果要使用数据库当分布式锁，则应该把作为锁的数据库与业务数据库分开
     */
    @GetMapping("mysqlSingleLock")
    @Transactional(rollbackFor = Exception.class)
    public void mysqlSingleLock() throws Exception {
        log.info("进入 mysqlSingleLock 方法");
        DistributeLock demo = distributeLockDao.selectForUpdate("demo");
        if (null == demo){
            throw new Exception("分布式锁找不到");
        }
        log.info("获取到 mysqlSingleLock 锁");
        Thread.sleep(60000);
    }

}
